/*	VultureHarass class definition.
 *
*/

#include "VultureHarass.h"

VultureHarass::VultureHarass(std::string incName, unsigned int frameInterval) :		Behavior(incName),
																					lastHarassFrame(0),
																					harassInterval(frameInterval)

{
	currentBaseScouting = 0;
	baseHarassed1 = NULL;
	baseHarassed2 = NULL;
	attackEnemyBase= false;
}

void VultureHarass::Enter()
{
	DEBUG_PRINT("VultureHarass(%p) entering.\n", this);
}

void VultureHarass::Execute()
{
	//BWAPI::Position attackPosition(BB->GetAttackPosition());

	std::list<BWAPI::Unit*>* vultures = BB->GetUnitsByTypeGeneral(BWAPI::UnitTypes::Terran_Vulture);

	if(!vultures )
	{
		control->FinishWithSuccess();
		return;
	}
	Base* baseToIgnore = NULL;
	Base*  baseToHarass = NULL;
	//Base*  baseHarassed = NULL;

	int maxSize = 0;
	int minSize=1000;
	if(BB->GetEnemyBases()->size() > 1) // else we have only scouted one base and can assume that's the main one
	{
		for(std::list<Base*>::iterator it = BB->GetEnemyBases()->begin(); it != BB->GetEnemyBases()->end(); it++)
		{
			if( (*it)->GetEnemyBuildingLocations()->size() > maxSize )
			{
				maxSize = (*it)->GetEnemyBuildingLocations()->size();
				baseToIgnore = *it;
			}
			if( (*it)->GetEnemyBuildingLocations()->size() < minSize )
			{
				minSize = (*it)->GetEnemyBuildingLocations()->size();
				//baseToIgnore = *it;
			}
			

		}
		for(std::list<Base*>::iterator it = BB->GetEnemyBases()->begin(); it != BB->GetEnemyBases()->end(); it++)
		{
			if( (*it)!= baseToIgnore && (*it)!= baseHarassed1 && (*it)!= baseHarassed2)
			{
				
				baseToHarass = *it;
				//baseHarassed=*it;
				break;
			}
			//else if((*it)!= baseToIgnore && baseHarassed1 && (*it)->GetEnemyBuildingLocations()->size() > 0)
			//{
			//	baseToHarass = *it;
			//	break;

			//}

		}

	}
	if(baseToHarass && !attackEnemyBase)
	{
		for(std::list<BWAPI::Unit*>::iterator it1 = vultures->begin(); it1 != vultures->end(); it1++)
		{
			if(((*it1)->getRemainingBuildTime()>0))
				continue;
			BWAPI::Unit* theUnit = (*it1);
			theUnit->attack(BWAPI::Position(baseToHarass->GetBaseLocation()),true);
			if(theUnit->getDistance(BWAPI::Position(baseToHarass->GetBaseLocation())) < 400 && !theUnit->isAttacking()) //if vulture arrived at the enemy base.
			{	
				if(findNearestEnemyWorker(theUnit))
				{
					theUnit->attack(findNearestEnemyWorker(theUnit),true);
					theUnit->useTech(BWAPI::TechTypes::Spider_Mines,findNearestEnemyWorker(theUnit)->getPosition());
				}
				else if(findNearestEnemy(theUnit))
				{
					theUnit->attack(findNearestEnemy(theUnit),true);
					//theUnit->useTech(BWAPI::TechTypes::Spider_Mines,findNearestEnemy(theUnit)->getPosition());
				}
				else if(!findNearestEnemy(theUnit))
				{
					if(!baseHarassed1)
						baseHarassed1=baseToHarass;
					else if(!baseHarassed2 && BB->GetEnemyBases()->size() > 2)
						baseHarassed2=baseToHarass;
					else
						attackEnemyBase=true;
						//attack enemy base
					
					break;
				}

				//else 
				//{
				//	//baseToHarass=null;
				//	std::list<Base*>* bases = BB->GetBases();
				//	//theUnit->move(BWAPI::Position(bases->front()->GetBaseLocation()));

				//	Base* Mbase = bases->front();
				//	BWAPI::Position MBasePos;
				//	MBasePos.x() = (Mbase->GetBaseLocation().x()*TILE_SIZE);
				//	MBasePos.y() = (Mbase->GetBaseLocation().y()*TILE_SIZE);
				//	theUnit->move(MBasePos);

				//}

			}
		}

	}
	if(attackEnemyBase)
	{
		for(std::list<BWAPI::Unit*>::iterator it1 = vultures->begin(); it1 != vultures->end(); it1++)
		{
			if(((*it1)->getRemainingBuildTime()>0))
				continue;
			BWAPI::Unit* theUnit = (*it1);
			theUnit->attack(BWAPI::Position(baseToIgnore->GetBaseLocation()),true);

		}

	}

	//for(std::list<BWAPI::Unit*>::iterator it1 = vultures->begin(); it1 != vultures->end(); it1++)
	//{
	//	if(((*it1)->getRemainingBuildTime()>0))
	//		continue;
	//	BWAPI::Unit* theUnit = (*it1);
	//	std::list<Base*>* bases = BB->GetBases();
	//	//theUnit->move(BWAPI::Position(bases->front()->GetBaseLocation()));

	//	Base* Mbase = bases->front();

	//	//if(!baseToHarass && !findNearestEnemy(theUnit) && theUnit->getDistance(BWAPI::Position(Mbase->GetBaseLocation())) > 500)
	//	if(!findNearestEnemy(theUnit) && theUnit->getDistance(BWAPI::Position(baseToHarass->GetBaseLocation())) < 400)
	//	{


	//		//BWAPI::Position MBasePos;
	//		//MBasePos.x() = (Mbase->GetBaseLocation().x()*TILE_SIZE);
	//		//MBasePos.y() = (Mbase->GetBaseLocation().y()*TILE_SIZE);
	//		//theUnit->move(MBasePos);
	//		//baseToHarass=NULL;
	//		//break;

	//	}
	//}


	// control cleanup
	control->FinishWithSuccess();

}

void VultureHarass::Exit()
{
	DEBUG_PRINT("Exiting VultureHarass behavior.\n");
}

bool VultureHarass::CheckConditions()
{
	std::list<BWAPI::Unit*>* vultures = BB->GetUnitsByTypeGeneral(BWAPI::UnitTypes::Terran_Vulture);
	if((vultures) && (vultures->size()>3))
	{
		//if(BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Spider_Mines) && BWAPI::Broodwar->self()->getUpgradeLevel(BWAPI::UpgradeTypes::Ion_Thrusters) > 0)

			return true;
	}
	return false;

}

BWAPI::Unit* VultureHarass::findNearestEnemyWorker(BWAPI::Unit* myVulture)
{
	BWAPI::Unit* currentBest = 0;
	BWAPI::Position myPos = myVulture->getPosition(), closePos;
	double bestDist=-1;
	for(std::set<BWAPI::Unit*>::const_iterator i=BWAPI::Broodwar->getAllUnits().begin();i!=BWAPI::Broodwar->getAllUnits().end();i++)
	{
		if(!(*i) || !(*i)->exists())
			continue;
		if ((*i)->getPlayer()->isEnemy(myVulture->getPlayer()) && (*i)->getType().isWorker())
		{
			BWAPI::Position testPos = (*i)->getPosition();
			double d = testPos.getDistance(myPos);
			if(!currentBest) {
				currentBest = (*i);
				bestDist = d;
			}
			else {
				if(d<bestDist) {
					currentBest = (*i);
					bestDist = d;
				}
			}
		}
	}
	if(currentBest) {
		//BWAPI::Broodwar->sendText("Nearest enemy: %s", currentBest->getType().getName().c_str());
	}
	else {
		//BWAPI::Broodwar->sendText("No nearest enemy");
	}
	return currentBest;
}

BWAPI::Unit* VultureHarass::findNearestEnemy(BWAPI::Unit* myVulture)
{
	BWAPI::Unit* currentBest = 0;
	BWAPI::Position myPos = myVulture->getPosition(), closePos;
	double bestDist=-1;
	for(std::set<BWAPI::Unit*>::const_iterator i=BWAPI::Broodwar->getAllUnits().begin();i!=BWAPI::Broodwar->getAllUnits().end();i++)
	{
		if(!(*i) || !(*i)->exists())
			continue;
		if ((*i)->getPlayer()->isEnemy(myVulture->getPlayer()))
		{
			BWAPI::Position testPos = (*i)->getPosition();
			double d = testPos.getDistance(myPos);
			if(!currentBest) {
				currentBest = (*i);
				bestDist = d;
			}
			else {
				if(d<bestDist) {
					currentBest = (*i);
					bestDist = d;
				}
			}
		}
	}
	if(currentBest) {
		//BWAPI::Broodwar->sendText("Nearest enemy: %s", currentBest->getType().getName().c_str());
	}
	else {
		//BWAPI::Broodwar->sendText("No nearest enemy");
	}
	return currentBest;
}